# -*- coding: utf-8 -*-
"""
---------------------------------------
@File    ：ip_crontab.py
@Author  ：liyunhui
@Date    ：2024/9/16 下午3:33 
@explain : ip代理划分
---------------------------------------
"""
import time
from config import config
from datetime import datetime
from methods.custom_log import create_logging
from methods.redis_connect import get_redis_cli


class IpCrontabHandler:

    def __init__(self):
        self.is_china_use_ip = config.use_ips + ":is_china"
        self.no_china_use_ip = config.use_ips + ":no_china"
        self.proxy_port = config.proxy_port
        self.logging = create_logging("ip_crontab")
        self.classify_key = config.proxy_classify_key + ":*"
        self.redis_cli = get_redis_cli()

    def get_proxy_classify(self):
        """
        获取各个爬虫的分类
        """
        return self.redis_cli.keys(self.classify_key)

    def get_classify_info(self, classify_key):
        """
        获取指定分类的信息
        """
        return self.redis_cli.hgetall(classify_key)

    def get_type_proxy(self, ip_type, ip_check_time):
        """
        获取指定类型的代理并顺带检查代理是否在更新时间范围内
        """
        if "国内外" in ip_type:
            key = config.use_ips + ":*"
        elif "国内" in ip_type:
            key = self.is_china_use_ip + ":*"
        else:
            key = self.no_china_use_ip + ":*"

        proxies = []
        # 批量获取数据
        keys = self.redis_cli.keys(key)
        for proxy_key in keys:
            ip_data = self.redis_cli.hgetall(proxy_key)
            proxies.append(ip_data)
        # 提前过滤有效代理
        current_timestamp = time.time()
        valid_proxies = []
        for proxy in proxies:
            proxy_update_time_str = proxy.get('update_time')
            if proxy_update_time_str:
                proxy_update_time = datetime.strptime(proxy_update_time_str, '%Y-%m-%d %H:%M:%S')
                proxy_update_timestamp = time.mktime(proxy_update_time.timetuple())
                if current_timestamp - proxy_update_timestamp <= (ip_check_time-40):
                    valid_proxies.append(proxy)
                else:
                    self.logging.info(f"代理 {proxy.get('public_ip')} 已过期")
        return valid_proxies

    def handler(self):
        classify_list = self.get_proxy_classify()

        for classify in classify_list:
            classify_info = self.get_classify_info(classify)
            ip_type = classify_info.get("ip_type", "")
            ip_check_time = int(classify_info.get("ip_check_time", 600))
            proxies = self.get_type_proxy(ip_type, ip_check_time)
            max_use_per_min = int(classify_info.get("max_use_per_min", 0))  # 每分钟最大使用次数

            # 获取分类名称并构造目标key
            classify_name = classify.rsplit(':', 1)[-1]
            target_key = config.total_classify_proxy + f":{classify_name}"

            if proxies:
                # 根据最大使用次数重复代理列表
                limited_proxies = proxies * max_use_per_min
                self.logging.info(f"{classify_name} --- 本次下发代理: {len(limited_proxies)}个")

                # 使用pipeline减少redis I/O
                with self.redis_cli.pipeline() as pipe:
                    for proxy in limited_proxies:
                        pipe.rpush(target_key, proxy.get("public_ip"))
                    # 批量设置过期时间为1分钟
                    pipe.expire(target_key, 60)
                    pipe.execute()
            else:
                self.logging.info(f'该分类没有可用的代理：{classify}')


if __name__ == '__main__':
    ip_crontab = IpCrontabHandler()
    ip_crontab.handler()
